package com.itheima.blog.article.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.itheima.api.client.dto.TBannerDto;
import com.itheima.blog.article.constants.SortConstants;
import com.itheima.blog.article.dto.TBlogDto;
import com.itheima.api.client.AdminClient;
import com.itheima.api.client.blogAdminReport.ReportVO;
import com.itheima.api.client.dto.Tag;
import com.itheima.blog.article.domain.po.vo.CategoryVO;
import com.itheima.blog.article.dto.contributeForLastYearDTO;
import com.itheima.blog.article.entity.TBlog;
import com.itheima.blog.article.entity.TComment;
import com.itheima.blog.article.mapper.TBlogMapper;
import com.itheima.blog.article.mapper.TCommentMapper;
import com.itheima.blog.article.mapper.TCommentMapper;
import com.itheima.blog.article.query.CommentQuery;
import com.itheima.blog.article.query.PageQueryDTO;
import com.itheima.blog.article.query.FilePageQuery;
import com.itheima.blog.article.query.categoryQuery;
import com.itheima.blog.article.service.ITBlogService;
import com.itheima.common.domain.PageReqDto;
import com.itheima.common.domain.PageResDto;
import com.itheima.blog.article.service.ITCommentService;
import com.itheima.blog.article.vo.ReplyVO;
import com.itheima.blog.util.UserThreadLocalUtils;
import com.itheima.common.domain.PageResDto;
import com.itheima.common.exception.BadRequestException;
import com.itheima.common.exception.BlogException;
import com.itheima.common.utills.BeanUtils;
import com.itheima.common.query.PageDTO;
import com.itheima.common.utills.BeanUtils;
import com.itheima.common.utills.CollUtils;
import lombok.RequiredArgsConstructor;
import com.itheima.common.utills.BeanUtils;
import com.itheima.common.utills.CollUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static com.itheima.common.utills.MapToClacc.setObject;
import java.util.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

import static com.itheima.common.constants.Constant.BLOG_CLICK_KEY;

/**
 * <p>
 * 博客文章表 服务实现类
 * </p>
 *
 * @author lin
 * @since 2023-07-12
 */
@Service
@RequiredArgsConstructor
public class TBlogServiceImpl extends ServiceImpl<TBlogMapper, TBlog> implements ITBlogService {

    private final TCommentMapper commentMapper;
    private final StringRedisTemplate redisTemplate;
    private final TBlogMapper blogMapper;
    private final AdminClient adminClient;

    /**
     * 文章详情展示
     * 展示作者信息(author)、
     * 浏览量(click_count)、
     * 分类名(category_name)、
     * 文章详情(title\summary\content)、
     * 时间(update_time)
     *
     * @param blogId
     * @return
     */
    @Override
    public List<TBlog> blogDetail(Long blogId) {
        if (blogId == null) {
            throw new BlogException("错误的请求参数");
        }
        List<TBlog> list = lambdaQuery().eq(TBlog::getId, blogId)
                .list();

        redisTemplate.opsForHash().increment(BLOG_CLICK_KEY,blogId.toString(),1);
        return list;
    }

    @Override
    public ReportVO fingLogAndCommentNumber() {
        Long logCount = count();

        QueryWrapper<TComment> wrapper = new QueryWrapper<>();
        Long commentCount = commentMapper.selectCount(wrapper);

        ReportVO reportVO = new ReportVO();
        reportVO.setLogNumber(logCount);
        reportVO.setCommentNumber(commentCount);
        return reportVO;
    }

    @Override
    public List<Long> classificationNumber(List<Integer> categoryIds) {
        List<Long> number = new ArrayList<>(categoryIds.size());
        for (Integer categoryId : categoryIds) {
            long count = lambdaQuery().eq(TBlog::getCategoryId, categoryId).count();
            number.add(count);
        }
        return number;
    }

    @Override
    public ReportVO labelNumber() {
        ReportVO reportVO = new ReportVO();

        QueryWrapper<TBlog> wrapper = new QueryWrapper<TBlog>()
                .select("tagname , count(*) ")
                .groupBy("tagname");
        List<Map<String, Object>> list = listMaps(wrapper);

        List<String> labelName = new ArrayList<>();
        List<Long> number = new ArrayList<>();
        for (Map<String, Object> s : list) {
            labelName.add(s.get("tagname").toString());
            number.add((Long) s.get("count(*)"));
        }
        reportVO.setLabelName(labelName);
        reportVO.setNumber(number);
        return reportVO;
    }

    @Override
    public List<ReportVO> provinceBlogs(Integer type) {

        List<ReportVO> volist = new ArrayList<>();
        List<String> province = new ArrayList<>();
        List<Long> number = new ArrayList<>();
        LocalDateTime start = LocalDateTime.now();
        LocalDateTime end = LocalDateTime.now();
        LocalDateTime date = LocalDateTime.now();
//        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
        //准备日期
        //今天
        if (type == 1) {
            start = date.with(LocalTime.MIN);
            end = date.with(LocalTime.MAX);
        } else if (type == 2) {
            //当月
            start = date.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
            end = date.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);
        } else if (type == 3) {
            start = date.with(TemporalAdjusters.firstDayOfYear()).with(LocalTime.MIN);
            end = date.with(TemporalAdjusters.lastDayOfYear()).with(LocalTime.MAX);
        }


        QueryWrapper<TBlog> qw = new QueryWrapper<>();
        qw.select("province,count(*) num");//查询自定义列
        qw.between("create_time", start, end);
        qw.groupBy("province");
        List<Map<String, Object>> list = listMaps(qw);

        for (Map<String, Object> stringObjectMap : list) {
            ReportVO reportVO = new ReportVO();
            setObject(reportVO, stringObjectMap);
//            province.add(stringObjectMap.get("province").toString());
//            number.add((Long) stringObjectMap.get("count(*)"));
            volist.add(reportVO);
        }
//        reportVO.setProvince(province);
//        reportVO.setNumber(number);
        return volist;

//        DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd");
//        LocalDate now = LocalDate.now();
//        String day = now.format(df);
//        String[] split = day.split("-");
//        String month = split[0] + "-" + split[1];
//        String year = split[0];
//
//        if (type == 1) {
//            for (TBlog tBlog : tBlogList) {
//                String format = tBlog.getCreateTime().format(df);
//                if (format.equals(day)) {
//                    list.add(tBlog);
//                }
//            }
//            number.add((long) list.size());
//        } else if (type == 2) {
//            for (TBlog tBlog : tBlogList) {
//                String format = tBlog.getCreateTime().format(df);
//                String[] split2 = format.split("-");
//                String month2 = split2[0] + "-" + split2[1];
//
//                if (month2.equals(month)) {
//                    list.add(tBlog);
//                }
//            }
//        } else if (type == 3) {
//            for (TBlog tBlog : tBlogList) {
//                String format = tBlog.getCreateTime().format(df);
//                String[] split3 = format.split("-");
//                String year3 = split3[0];
//
//                if (year3.equals(year)) {
//                    list.add(tBlog);
//                }
//            }
//        }


    }

    @Override
    public ReportVO contributeForLastYear() {
        //select distinct(date_format(create_time,'%y-%m-%d')) as day ,count(*)  as daycount from t_blog   where create_time between '2022-07-12' and '2023-07-13' group by day;
        ReportVO reportVO = new ReportVO();
        List<String> lastYear = new ArrayList<>();
        List<Long> number = new ArrayList<>();

        LocalDateTime end = LocalDateTime.now();
        LocalDateTime start = end.minusYears(1);

        List<contributeForLastYearDTO> tBlogList = blogMapper.contributeForLastYear(start, end);
        for (contributeForLastYearDTO c : tBlogList) {
            lastYear.add(c.getDay());
            number.add(c.getCount());
        }
        reportVO.setLastYear(lastYear);
        reportVO.setNumber(number);
        return reportVO;
    }

    @Override
    public PageDTO<CategoryVO> categoryPage(categoryQuery query) {

        Page<TBlog> pageCondition = query.toMpPageDefaultSortByCreateTimeDesc();
        Page<TBlog> page = lambdaQuery()
                .eq(TBlog::getCategoryId, query.getCategoryId())
                .page(pageCondition);
        List<TBlog> records = page.getRecords();
        if (CollUtils.isEmpty(records)) {
            return PageDTO.empty(page);
        }


        //调用feign查找标签类
        List<String> tagIds = records.stream().map(TBlog::getTagId).collect(Collectors.toList());
        if (CollUtils.isEmpty(tagIds)) {
            return PageDTO.of(page, CollUtils.emptyList());
        }
        List<Integer> integerList = new ArrayList<>(tagIds.size());
        for (String tagId : tagIds) {
            String[] split = tagId.split(",");
            for (int i = 0; i < split.length; i++) {
                integerList.add(Integer.valueOf(split[i]));
            }
        }
        List<Tag> tagDtos = adminClient.listWithIds(integerList);


        //博客map，博客id和博客类
        Map<Long, TBlog> tBlogMap = records.stream().collect(Collectors.toMap(TBlog::getId, tblog -> tblog));
        //关联map，博客id和标签id
        Map<Long, String> tagIdMap = records.stream().collect(Collectors.toMap(TBlog::getId, TBlog::getTagId));
        //标签map，标签id和标签名
        Map<Integer, String> tagName = tagDtos.stream().collect(Collectors.toMap(Tag::getId, Tag::getContent));

        List<CategoryVO> vos = new ArrayList<>(records.size());
        for (TBlog record : records) {
            Long id = record.getId();
            //获取每一个类的博客类和标签id
            TBlog tBlog = tBlogMap.get(id);
            String tagIdStr = tagIdMap.get(id);

            List<String> contentList = new ArrayList<>();
            for (Integer tagId : splitTagid(tagIdStr)) {
                contentList.add(tagName.get(tagId));
            }

            CategoryVO vo = CategoryVO.builder()
                    .title(tBlog.getTitle())
                    .createTime(tBlog.getCreateTime())
                    .contentList(contentList)
                    .build();
            vos.add(vo);
        }

        return PageDTO.of(page, vos);
    }

    private List<Integer> splitTagid(String tagId) {
        List<Integer> integerList = new ArrayList<>();
        String[] split = tagId.split(",");
        for (int i = 0; i < split.length; i++) {
            integerList.add(Integer.valueOf(split[i]));
        }
        return integerList;
    }


    @Override
    public PageDTO<CategoryVO> filePage(FilePageQuery filePageQuery) {
        List<TBlog> records = new ArrayList<>();
        Page<TBlog> page = new Page<>();


//        String date = "2023-07";
//        date = date + "-01 00:00:00";
//        System.out.println(date);
//        LocalDateTime localTime = LocalDateTime.parse(date, df);
//        System.out.println(localTime);
//        LocalDateTime start = localTime.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
//        LocalDateTime end = localTime.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);

        String date = filePageQuery.getDate() + "-01 00:00:00";
        DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime localDateTime = LocalDateTime.parse(date, fmt);
        LocalDateTime start = localDateTime.with(TemporalAdjusters.firstDayOfMonth()).with(LocalTime.MIN);
        LocalDateTime end = localDateTime.with(TemporalAdjusters.lastDayOfMonth()).with(LocalTime.MAX);


        if (filePageQuery.getType() == 0) {
            Page<TBlog> pageCondition = filePageQuery.toMpPageDefaultSortByCreateTimeDesc();
            page = lambdaQuery()
                    .between(TBlog::getCreateTime, start, end)
                    .page(pageCondition);
            records = page.getRecords();
        } else {
            Page<TBlog> pageCondition = filePageQuery.toMpPage("create_time", true);
            page = lambdaQuery()
                    .between(TBlog::getCreateTime, start, end)
                    .page(pageCondition);
            records = page.getRecords();
        }

        //调用feign查找标签类
        List<String> tagIds = records.stream().map(TBlog::getTagId).collect(Collectors.toList());
        if (CollUtils.isEmpty(tagIds)) {
            return PageDTO.of(page, CollUtils.emptyList());
        }
        List<Integer> integerList = new ArrayList<>(tagIds.size());
        for (String tagId : tagIds) {
            String[] split = tagId.split(",");
            for (int i = 0; i < split.length; i++) {
                integerList.add(Integer.valueOf(split[i]));
            }
        }
        List<Tag> tagDtos = adminClient.listWithIds(integerList);


        //博客map，博客id和博客类
        Map<Long, TBlog> tBlogMap = records.stream().collect(Collectors.toMap(TBlog::getId, tblog -> tblog));
        //关联map，博客id和标签id
        Map<Long, String> tagIdMap = records.stream().collect(Collectors.toMap(TBlog::getId, TBlog::getTagId));
        //标签map，标签id和标签名
        Map<Integer, String> tagName = tagDtos.stream().collect(Collectors.toMap(Tag::getId, Tag::getContent));

        List<CategoryVO> vos = new ArrayList<>(records.size());
        for (TBlog record : records) {
            Long id = record.getId();
            //获取每一个类的博客类和标签id
            TBlog tBlog = tBlogMap.get(id);
            String tagIdStr = tagIdMap.get(id);

            List<String> contentList = new ArrayList<>();
            for (Integer tagId : splitTagid(tagIdStr)) {
                contentList.add(tagName.get(tagId));
            }

            CategoryVO vo = CategoryVO.builder()
                    .title(tBlog.getTitle())
                    .createTime(tBlog.getCreateTime())
                    .contentList(contentList)
                    .build();
            vos.add(vo);
        }

        return PageDTO.of(page, vos);
    }

    @Override
    public PageResDto<TBlog> findBlogByPage(TBlogDto tBlogDto) {
        //获取分页条件
        Integer page = tBlogDto.getPage();
        Integer size = tBlogDto.getSize();
        int i = (page - 1) * size;
        //获取分页数据
        Page<TBlog> bannerPage = lambdaQuery()
                .orderByDesc(tBlogDto.getSort().equals(SortConstants.DEFAULT),TBlog::getCreateTime)
                .orderByDesc(tBlogDto.getSort().equals(SortConstants.HEAT),TBlog::getHeat)
                .orderByDesc(tBlogDto.getSort().equals(SortConstants.CLICK),TBlog::getClickCount)
                .page(new Page<>(i, size));

        List<TBlog> records = bannerPage.getRecords();
        return new PageResDto<>(tBlogDto,bannerPage.getTotal(), records);
    }



    /**
     * 根据分类查询点击量前十条
     * click_count 博客点击数
     * category_id  博客分类UID
     * category_name 分类名
     * is_publish 是否发布/上架：0：否，1：是
     *
     * @param categoryId
     * @return
     */
    @Override
    public List<TBlog> relatedBlog(Long categoryId) {
        // 根据点击量 和categoryId 查询前十条
        //查询出所有的分类id
        //分类名称
        if (categoryId == null) {
            return CollUtils.emptyList();
        }
        Page<TBlog> page = new Page<>();
        page.setSize(10);
        page.setCurrent(1);
        Page<TBlog> pageData = lambdaQuery()
                .eq(TBlog::getCategoryId,categoryId)
                .orderByDesc(TBlog::getClickCount)
                .page(page);
        List<TBlog> records = pageData.getRecords();
        return records;
    }
}